🌐 [translation-sync] Add Type Hints section to More Language Features lecture#2
🌐 [translation-sync] Add Type Hints section to More Language Features lecture#2
Conversation
|
| Criterion | Score |
|---|---|
| Accuracy | 9/10 |
| Fluency | 9/10 |
| Terminology | 9/10 |
| Formatting | 8/10 |
| Overall | 8.9/10 |
Summary: The translation is of high quality overall, with accurate rendering of newly added sections (especially Type hints) and strong technical terminology consistency. The most critical issue is the structural duplication of the header/anchor block in the preamble, which would cause rendering problems and must be fixed. A minor accuracy issue exists in the Overview where 'type hints' is omitted from the list of topics. The translation of the new Type hints section is fluent and accurate, with only a minor quibble about 'humans' being narrowed to 'developers'. Formatting is well preserved across all changed sections. The newly added 'Type hints' section (## 类型提示) is translated with high accuracy and natural fluency, correctly rendering all subsections including the table of common types. Technical terminology is consistently and correctly handled throughout the changed sections: '迭代器' for iterators, '可迭代对象' for iterables, '生成器' for generators, '装饰器' for decorators, '描述符' for descriptors, '类型提示' for type hints. The * and ** operators section is well translated, correctly distinguishing '位置参数' (positional arguments) and '关键字参数' (keyword arguments), and maintaining the technical precision of the original. The generator expressions and generator functions sections read naturally in Chinese and preserve all code, comments, and MyST formatting correctly. The 'Why use type hints?' subsection (### 为什么使用类型提示?) preserves the numbered list structure and bold formatting for all four reasons accurately.
⚠️ Markdown Syntax Errors (CRITICAL)
- 🔴 Duplicate content: The preamble/frontmatter section contains duplicate entries - both '(python_advanced_features)=' anchor and the raw jupyter div/header block appear twice, followed by '# 更多语言特性' appearing twice. This structural duplication would cause rendering issues.
Suggestions:
- Overview section: '本讲涵盖了多种主题,包括迭代器、装饰器和描述符,以及生成器。' — The source also mentions 'type hints' (类型提示) in this list: 'including iterators, type hints, decorators and descriptors, and generators.' The translation omits '类型提示', which is an accuracy issue given that the Type hints section was newly added in this PR.
-
Type hints section: '作为面向开发者和工具的文档使用。' — Source says 'for humans and tools', so '开发者' (developers) is narrower than 'humans'. Consider '面向人类和工具的文档' or '供人阅读和供工具使用的文档' to be more accurate.
-
Hints don't enforce types: '对于 Python 初学者来说,有一点很重要' — Source says 'An important point for new Python programmers', which is accurate, but the heading translation '提示不强制类型检查' adds '检查' which is not in the source heading 'Hints don't enforce types'. Consider '提示不强制类型' to stay closer to the source.
-
Iterators in for loops: The code comment in the for loop example '# do something' is left in English inside a no-execute code block. While code comments are often left untranslated, this is consistent with the source so it is acceptable, but worth noting the pattern is inconsistent — some code comments in the changed sections remain in English while explanatory text around them is translated.
🔍 Diff Quality
| Check | Status |
|---|---|
| Scope Correct | ✅ |
| Position Correct | ❌ |
| Structure Preserved | ❌ |
| Heading-map Correct | ✅ |
| Overall | 5/10 |
Summary: The heading-map is correctly updated with new Type hints entries and renamed headings, but the target document is corrupted by a duplicated anchor/header block near the top, breaking document structure and position correctness.
Issues:
- The target document 'after' version contains a duplicated header block: the
(python_advanced_features)=anchor and the raw jupyter div header appear twice, followed by# 更多语言特性appearing twice before the## 概述section. - The new 'Type hints' section content is correctly added in the target, but its placement is preceded by the duplicate header issue which disrupts document structure.
- Several heading capitalizations changed in the source (e.g., 'Iterables and Iterators' → 'Iterables and iterators', 'Iterators in For Loops' → 'Iterators in for loops', etc.) and the heading-map correctly reflects these, but the duplicate header block is a structural corruption not present in the source 'after' version.
- The source 'after' removes the matplotlib i18n font setup code block that was in the translation's 'before' version — the target 'after' also correctly removes it, which is appropriate.
- The
(iterators)=and(descriptors)=and(paf_generators)=anchors in the target 'after' have an extra blank line inserted after them before the heading, which differs from the source pattern.
This review was generated automatically by action-translation review mode.
|
@HumphreyYang same with this PR |
There was a problem hiding this comment.
Many thanks @mmcky,
I’ve reviewed this and have a few observations:
- It correctly captures changes in the source file: QuantEcon/lecture-python-programming#488 and did a good job translating them.
- However, it also appears to modify other parts of the lectures that weren’t changed.
More specifically, it updates several lines throughout the lecture that are not part of that PR. This suggests the agents may be seeing more context than intended. - It also tends to revert code comments back to English, but it is also related to point 2 above. Those code comments change are not part of the source PR.
Would it be possible to limit the context to only the changes introduced in the PR?
| @@ -394,23 +407,23 @@ legend_kargs = {'bbox_to_anchor': (0., 1.02, 1., .102), | |||
| β_0s = [10, 20, 30] | |||
| β_1s = [1, 2, 3] | |||
|
|
|||
| # 使用 for 循环绘制折线 | |||
| # Use a for loop to plot lines | |||
| def generate_plots(β_0s, β_1s, idx, line_kargs, legend_kargs): | |||
| label_list = [] | |||
| for βs in zip(β_0s, β_1s): | |||
|
|
|||
| # 使用 * 解包元组 βs 和 generate_data 函数的元组输出 | |||
| # 使用 ** 解包折线关键字参数字典 | |||
| # Use * to unpack tuple βs and the tuple output from the generate_data function | |||
| # Use ** to unpack the dictionary of keyword arguments for lines | |||
| ax[idx].plot(*generate_data(*βs), **line_kargs) | |||
|
|
|||
| label_list.append(f'$β_0 = {βs[0]}$ | $β_1 = {βs[1]}$') | |||
|
|
|||
| # 使用 ** 解包图例关键字参数字典 | |||
| # Use ** to unpack the dictionary of keyword arguments for legends | |||
| ax[idx].legend(label_list, **legend_kargs) | |||
|
|
|||
| generate_plots(β_0s, β_1s, 0, line_kargs, legend_kargs) | |||
|
|
|||
| # 我们可以轻松地重用和更新参数 | |||
| # We can easily reuse and update our parameters | |||
| β_1s.append(-2) | |||
| β_0s.append(40) | |||
| line_kargs['lw'] = 2 | |||
There was a problem hiding this comment.
This is reverting code comments back to English.
| print(ls) | ||
|
|
||
| # 注意这些是关键字参数 | ||
| # Note that these are keyword arguments |
There was a problem hiding this comment.
Similar to above. It seems that action agents is not handling code comments well.
| ## 类型提示 | ||
|
|
||
| ```{index} single: Python; Type Hints | ||
| ``` | ||
|
|
||
| Python 是一种*动态类型*语言,这意味着您无需声明变量的类型。 | ||
|
|
||
| (参见我们{doc}`之前关于动态类型与静态类型的讨论 <need_for_speed>`。) | ||
|
|
||
| 然而,Python 支持可选的**类型提示**(也称为类型注解),允许您指明变量、函数参数和返回值的预期类型。 | ||
|
|
||
| 类型提示从 Python 3.5 开始引入,并在后续版本中不断演进。此处展示的所有语法均适用于 Python 3.9 及更高版本。 | ||
|
|
||
| ```{note} | ||
| 类型提示在*运行时会被 Python 解释器忽略*——它们不会影响代码的执行方式。它们纯粹是信息性的,作为面向开发者和工具的文档使用。 | ||
| ``` | ||
|
|
||
| ### 基本语法 | ||
|
|
||
| 类型提示使用冒号 `:` 来注解变量和参数,使用箭头 `->` 来注解返回类型。 | ||
|
|
||
| 下面是一个简单的示例: | ||
|
|
||
| ```{code-cell} python3 | ||
| def greet(name: str, times: int) -> str: | ||
| return (name + '! ') * times | ||
|
|
||
| greet('hello', 3) | ||
| ``` | ||
|
|
||
| 在这个函数定义中: | ||
|
|
||
| - `name: str` 表示 `name` 预期为字符串类型 | ||
| - `times: int` 表示 `times` 预期为整数类型 | ||
| - `-> str` 表示该函数返回一个字符串 | ||
|
|
||
| 您也可以直接对变量进行注解: | ||
|
|
||
| ```{code-cell} python3 | ||
| x: int = 10 | ||
| y: float = 3.14 | ||
| name: str = 'Python' | ||
| ``` | ||
|
|
||
| ### 常用类型 | ||
|
|
||
| 最常用的类型提示是内置类型: | ||
|
|
||
| | 类型 | 示例 | | ||
| |-----------|----------------------------------| | ||
| | `int` | `x: int = 5` | | ||
| | `float` | `x: float = 3.14` | | ||
| | `str` | `x: str = 'hello'` | | ||
| | `bool` | `x: bool = True` | | ||
| | `list` | `x: list = [1, 2, 3]` | | ||
| | `dict` | `x: dict = {'a': 1}` | | ||
|
|
||
| 对于容器类型,您可以指定其元素的类型: | ||
|
|
||
| ```{code-cell} python3 | ||
| prices: list[float] = [9.99, 4.50, 2.89] | ||
| counts: dict[str, int] = {'apples': 3, 'oranges': 5} | ||
| ``` | ||
|
|
||
| ### 提示不强制类型检查 | ||
|
|
||
| 对于 Python 初学者来说,有一点很重要:类型提示在运行时*不会被强制执行*。 | ||
|
|
||
| 如果您传入"错误"的类型,Python 不会报错: | ||
|
|
||
| ```{code-cell} python3 | ||
| def add(x: int, y: int) -> int: | ||
| return x + y | ||
|
|
||
| # Passes floats — Python doesn't complain | ||
| add(1.5, 2.7) | ||
| ``` | ||
|
|
||
| 提示写的是 `int`,但 Python 会愉快地接受 `float` 参数并返回 `4.2`——同样不是 `int`。 | ||
|
|
||
| 这是与 C 或 Java 等静态类型语言的关键区别,在那些语言中,类型不匹配会导致编译错误。 | ||
|
|
||
| ### 为什么使用类型提示? | ||
|
|
||
| 如果 Python 会忽略它们,为什么还要费心呢? | ||
|
|
||
| 1. **可读性**:类型提示使函数签名具有自文档化的特性。读者可以立即了解函数期望的类型和返回的类型。 | ||
| 2. **编辑器支持**:VS Code 等集成开发环境利用类型提示来提供更好的自动补全、错误检测和内联文档。 | ||
| 3. **错误检查**:[mypy](https://mypy.readthedocs.io/) 和 [pyrefly](https://pyrefly.org/) 等工具通过分析类型提示,在*运行代码之前*就能发现错误。 | ||
| 4. **大语言模型生成的代码**:大型语言模型经常生成带有类型提示的代码,因此理解其语法有助于您阅读和使用这些输出。 | ||
|
|
||
| ### 科学 Python 中的类型提示 | ||
|
|
||
| 类型提示与{doc}`性能需求 <need_for_speed>`的讨论密切相关: | ||
|
|
||
| * [JAX](https://jax.readthedocs.io/) 和 [Numba](https://numba.pydata.org/) 等高性能库依赖于了解变量类型来编译快速的机器码。 | ||
| * 虽然这些库在运行时推断类型,而不是直接读取 Python 类型提示,但其*理念*是相同的——显式的类型信息能够实现优化。 | ||
| * 随着 Python 生态系统的发展,类型提示与性能工具之间的联系预计将进一步增强。 | ||
|
|
||
| 目前,类型提示在日常 Python 开发中的主要优势在于*清晰度和工具支持*,随着程序规模的增长,这一点的价值也愈发凸显。 | ||
|
|
There was a problem hiding this comment.
The tying section is correctly added and the translation is pretty good.
| @@ -524,20 +637,20 @@ def f(x): | |||
| def g(x): | |||
| return np.sqrt(42 * x) | |||
|
|
|||
| # 程序继续使用 f 和 g 进行各种计算 | |||
| # Program continues with various calculations using f and g | |||
| ``` | |||
|
|
|||
| 现在假设有一个问题:偶尔会有负数被传入到后续计算中的 `f` 和 `g`。 | |||
| 现在假设出现了一个问题:在后续计算中,`f` 和 `g` 偶尔会接收到负数。 | |||
|
|
|||
| 如果你尝试一下,你会看到当这些函数以负数调用时,它们返回一个名为 `nan` 的 NumPy 对象。 | |||
| 如果你尝试一下,你会发现当这些函数以负数作为参数被调用时,它们会返回一个名为 `nan` 的 NumPy 对象。 | |||
|
|
|||
| 这代表"非数字"(表明你正在尝试在未定义的点处求值一个数学函数)。 | |||
| 这代表"不是一个数"(表示你正在尝试在数学函数无定义的点处对其求值)。 | |||
|
|
|||
| 也许这不是我们想要的,因为它会导致其他难以在后期发现的问题。 | |||
| 也许这并不是我们想要的结果,因为它会导致其他难以在后续发现的问题。 | |||
|
|
|||
| 假设我们希望程序在发生这种情况时终止,并给出合理的错误消息。 | |||
| 假设我们希望程序在这种情况发生时终止,并给出一条合理的错误信息。 | |||
|
|
|||
| 这个更改很容易实现: | |||
| 这个改动实现起来很容易 | |||
|
|
|||
| ```{code-cell} python3 | |||
| import numpy as np | |||
| @@ -550,20 +663,20 @@ def g(x): | |||
| assert x >= 0, "Argument must be nonnegative" | |||
| return np.sqrt(42 * x) | |||
|
|
|||
| # 程序继续使用 f 和 g 进行各种计算 | |||
| # Program continues with various calculations using f and g | |||
| ``` | |||
|
|
|||
| 然而请注意,这里有一些重复,以两行相同代码的形式出现。 | |||
| 但请注意,这里存在一些重复,即两行完全相同的代码。 | |||
|
|
|||
| 重复使我们的代码更长且更难维护,因此我们应该尽力避免。 | |||
| 重复会使我们的代码更长、更难维护,因此是我们努力避免的事情。 | |||
|
|
|||
| 在这里这不是什么大问题,但现在想象一下,不是只有 `f` 和 `g`,而是我们有 20 个需要以完全相同方式修改的函数。 | |||
| 在这里这还不是大问题,但现在想象一下,不只是 `f` 和 `g`,而是有 20 个这样的函数需要以完全相同的方式进行修改。 | |||
|
|
|||
| 这意味着我们需要重复测试逻辑(即测试非负性的 `assert` 行)20 次。 | |||
| 这意味着我们需要重复测试逻辑(即检查非负性的 `assert` 语句)20 次。 | |||
|
|
|||
| 如果测试逻辑更长更复杂,情况就更糟了。 | |||
| 如果测试逻辑更长、更复杂,情况会更糟。 | |||
|
|
|||
| 在这种情况下,以下方法会更为简洁: | |||
| 在这种情况下,以下方法会更简洁 | |||
|
|
|||
| ```{code-cell} python3 | |||
| import numpy as np | |||
| @@ -582,44 +695,42 @@ def g(x): | |||
|
|
|||
| f = check_nonneg(f) | |||
| g = check_nonneg(g) | |||
| # 程序继续使用 f 和 g 进行各种计算 | |||
| # Program continues with various calculations using f and g | |||
| ``` | |||
|
|
|||
| 这看起来很复杂,所以让我们慢慢理解它。 | |||
| 这看起来很复杂,所以让我们慢慢地梳理一遍。 | |||
|
|
|||
| 为了理清逻辑,考虑当我们说 `f = check_nonneg(f)` 时会发生什么。 | |||
| 为了理清逻辑,考虑当我们写 `f = check_nonneg(f)` 时会发生什么。 | |||
|
|
|||
| 这调用了函数 `check_nonneg`,参数 `func` 设置为等于 `f`。 | |||
| 这会调用函数 `check_nonneg`,并将参数 `func` 设置为等于 `f`。 | |||
|
|
|||
| 现在 `check_nonneg` 创建了一个名为 `safe_function` 的新函数, | |||
| 该函数验证 `x` 为非负数,然后对其调用 `func`(与 `f` 相同)。 | |||
| 现在 `check_nonneg` 创建了一个名为 `safe_function` 的新函数,它先验证 `x` 是非负的,然后对其调用 `func`(即与 `f` 相同的函数)。 | |||
|
|
|||
| 最后,全局名称 `f` 被设置为等于 `safe_function`。 | |||
|
|
|||
| 现在 `f` 的行为符合我们的期望,`g` 也是如此。 | |||
| 现在 `f` 的行为符合我们的预期,`g` 也同样如此。 | |||
|
|
|||
| 与此同时,测试逻辑只需编写一次。 | |||
|
|
|||
| #### 引入装饰器 | |||
| #### 装饰器登场 | |||
|
|
|||
| ```{index} single: Python; Decorators | |||
| ``` | |||
|
|
|||
| 我们代码的最后一个版本仍然不够理想。 | |||
|
|
|||
| 例如,如果有人正在阅读我们的代码并想了解 `f` 的工作原理, | |||
| 他们会寻找函数定义,即: | |||
| 例如,如果有人在阅读我们的代码并想了解 `f` 的工作原理,他们会去寻找函数定义,即 | |||
|
|
|||
| ```{code-cell} python3 | |||
| def f(x): | |||
| return np.log(np.log(x)) | |||
| ``` | |||
|
|
|||
| 他们很可能会错过 `f = check_nonneg(f)` 这一行。 | |||
| 他们很可能会忽略 `f = check_nonneg(f)` 这一行。 | |||
|
|
|||
| 出于这个和其他原因,Python 引入了装饰器。 | |||
| 出于这个和其他原因,装饰器被引入了 Python。 | |||
|
|
|||
| 使用装饰器,我们可以将以下代码: | |||
| 使用装饰器,我们可以将以下代码 | |||
|
|
|||
| ```{code-cell} python3 | |||
| def f(x): | |||
| @@ -632,7 +743,7 @@ f = check_nonneg(f) | |||
| g = check_nonneg(g) | |||
| ``` | |||
|
|
|||
| 替换为: | |||
| 替换为 | |||
|
|
|||
| ```{code-cell} python3 | |||
| @check_nonneg | |||
| @@ -644,29 +755,30 @@ def g(x): | |||
| return np.sqrt(42 * x) | |||
| ``` | |||
|
|
|||
| 这两段代码做的事情完全相同。 | |||
| 这两段代码的作用完全相同。 | |||
|
|
|||
| 如果它们做的事情相同,我们真的需要装饰器语法吗? | |||
| 如果它们的作用相同,我们真的需要装饰器语法吗? | |||
|
|
|||
| 好吧,注意装饰器就位于函数定义的正上方。 | |||
| 注意,装饰器紧贴在函数定义的上方。 | |||
|
|
|||
| 因此,任何查看函数定义的人都会看到它们,并了解函数已被修改。 | |||
| 因此,任何查看函数定义的人都会看到它们,并意识到该函数已被修改。 | |||
|
|
|||
| 在许多人看来,这使得装饰器语法成为对语言的重大改进。 | |||
| 在许多人看来,这使得装饰器语法成为对 Python 语言的重大改进。 | |||
|
|
|||
| (descriptors)= | |||
|
|
|||
| ### 描述符 | |||
|
|
|||
| ```{index} single: Python; Descriptors | |||
| ``` | |||
|
|
|||
| 描述符解决了变量管理方面的一个常见问题。 | |||
| 描述符解决了一个关于变量管理的常见问题。 | |||
|
|
|||
| 为了理解这个问题,考虑一个模拟汽车的 `Car` 类。 | |||
|
|
|||
| 假设该类定义了变量 `miles` 和 `kms`,分别以英里和公里为单位给出行驶距离。 | |||
| 假设该类定义了变量 `miles` 和 `kms`,分别表示以英里和千米为单位的行驶距离。 | |||
|
|
|||
| 该类的一个高度简化的版本可能如下所示: | |||
| 该类的一个高度简化版本可能如下所示 | |||
|
|
|||
| ```{code-cell} python3 | |||
| class Car: | |||
| @@ -675,10 +787,10 @@ class Car: | |||
| self.miles = miles | |||
| self.kms = miles * 1.61 | |||
|
|
|||
| # 其他一些功能,细节省略 | |||
| # Some other functionality, details omitted | |||
| ``` | |||
|
|
|||
| 我们可能遇到的一个潜在问题是,用户更改了其中一个变量而没有更改另一个: | |||
| 我们可能遇到的一个潜在问题是,用户修改了其中一个变量但没有修改另一个 | |||
|
|
|||
| ```{code-cell} python3 | |||
| car = Car() | |||
| @@ -696,19 +808,19 @@ car.kms | |||
|
|
|||
| 在最后两行中,我们看到 `miles` 和 `kms` 不同步了。 | |||
|
|
|||
| 我们真正想要的是某种机制,使得每次用户设置其中一个变量时,*另一个会自动更新*。 | |||
| 我们真正想要的是某种机制,使得每当用户设置其中一个变量时,*另一个会自动更新*。 | |||
|
|
|||
| #### 解决方案 | |||
|
|
|||
| 在 Python 中,这个问题使用*描述符*来解决。 | |||
|
|
|||
| 描述符只是一个实现了某些方法的 Python 对象。 | |||
|
|
|||
| 这些方法在通过点属性符号访问对象时被触发。 | |||
| 当通过点属性符号访问该对象时,这些方法会被触发。 | |||
|
|
|||
| 理解这一点的最好方式是亲眼看看它的实际效果。 | |||
| 理解这一点的最佳方式是通过实际操作来观察。 | |||
|
|
|||
| 考虑这个 `Car` 类的替代版本: | |||
| 考虑这个 `Car` 类的替代版本 | |||
|
|
|||
| ```{code-cell} python3 | |||
| class Car: | |||
| @@ -735,7 +847,7 @@ class Car: | |||
| kms = property(get_kms, set_kms) | |||
| ``` | |||
|
|
|||
| 首先让我们检查一下是否获得了我们期望的行为: | |||
| 首先让我们验证我们得到了预期的行为 | |||
|
|
|||
| ```{code-cell} python3 | |||
| car = Car() | |||
| @@ -747,24 +859,23 @@ car.miles = 6000 | |||
| car.kms | |||
| ``` | |||
|
|
|||
| 是的,这就是我们想要的——`car.kms` 会自动更新。 | |||
| 是的,这正是我们想要的——`car.kms` 会自动更新。 | |||
|
|
|||
| #### 工作原理 | |||
|
|
|||
| 名称 `_miles` 和 `_kms` 是我们用来存储变量值的任意名称。 | |||
| `_miles` 和 `_kms` 这两个名称是我们用来存储变量值的任意名称。 | |||
|
|
|||
| 对象 `miles` 和 `kms` 是*属性*,一种常见的描述符。 | |||
| `miles` 和 `kms` 对象是*属性*,一种常见的描述符。 | |||
|
|
|||
| 方法 `get_miles`、`set_miles`、`get_kms` 和 `set_kms` 定义了 | |||
| 当你获取(即访问)或设置(绑定)这些变量时会发生什么: | |||
| 方法 `get_miles`、`set_miles`、`get_kms` 和 `set_kms` 定义了当你获取(即访问)或设置(绑定)这些变量时会发生什么 | |||
|
|
|||
| * 即所谓的 "getter" 和 "setter" 方法。 | |||
| * 即所谓的"getter"和"setter"方法。 | |||
|
|
|||
| Python 内置函数 `property` 接受 getter 和 setter 方法并创建一个属性。 | |||
|
|
|||
| 例如,在 `car` 作为 `Car` 的实例创建之后,对象 `car.miles` 是一个属性。 | |||
| 例如,在 `car` 作为 `Car` 的实例被创建后,对象 `car.miles` 就是一个属性。 | |||
|
|
|||
| 作为属性,当我们通过 `car.miles = 6000` 设置其值时,它的 setter 方法会被触发——在本例中是 `set_miles`。 | |||
| 作为一个属性,当我们通过 `car.miles = 6000` 设置其值时,其 setter 方法会被触发——在本例中为 `set_miles`。 | |||
|
|
|||
| #### 装饰器与属性 | |||
|
|
|||
| @@ -774,9 +885,9 @@ Python 内置函数 `property` 接受 getter 和 setter 方法并创建一个属 | |||
| ```{index} single: Python; Properties | |||
| ``` | |||
|
|
|||
| 如今,通过装饰器使用 `property` 函数非常普遍。 | |||
| 如今,通过装饰器来使用 `property` 函数非常普遍。 | |||
|
|
|||
| 这是我们 `Car` 类的另一个版本,与之前的工作方式相同,但现在使用装饰器来设置属性: | |||
| 这是我们 `Car` 类的另一个版本,它的功能与之前相同,但现在使用装饰器来设置属性 | |||
|
|
|||
| ```{code-cell} python3 | |||
| class Car: | |||
| @@ -806,9 +917,10 @@ class Car: | |||
|
|
|||
| 我们不会在这里介绍所有细节。 | |||
|
|
|||
| 如需进一步了解,可以参考[描述符文档](https://docs.python.org/3/howto/descriptor.html)。 | |||
| 如需进一步了解,你可以参阅[描述符文档](https://docs.python.org/3/howto/descriptor.html)。 | |||
|
|
|||
| (paf_generators)= | |||
|
|
|||
| ## 生成器 | |||
|
|
|||
| ```{index} single: Python; Generators | |||
| @@ -1079,7 +1191,6 @@ sum(draws) | |||
| * 避免了创建大型列表/元组的需要,以及 | |||
| * 提供了一个统一的迭代接口,可以在 `for` 循环中透明地使用。 | |||
|
|
|||
|
|
|||
| ## 练习 | |||
|
|
|||
|
|
|||
| @@ -1140,4 +1251,4 @@ for date in dates: | |||
| ``` | |||
|
|
|||
| ```{solution-end} | |||
| ``` No newline at end of file | |||
| ``` | |||
There was a problem hiding this comment.
All changes here are not in the source PR.
Automated Translation Sync
This PR contains automated translations from QuantEcon/lecture-python-programming.
Source PR
#488 - Add Type Hints section to More Language Features lecture
Files Updated
lectures/python_advanced_features.md.translate/state/python_advanced_features.md.ymlDetails
This PR was created automatically by the translation action.